test: attack nine index_am_support arms (#1236) - #1240
Conversation
No test changed and no code changed. index_am_support's only dated rows
were two premises about docs/features.md, reddened by a DOCS mutation,
which cannot reach one arm about what an index does. Eight behaviour arms
sat `never` beside them: unattacked rather than vacuous, the same shape the
first batch had.
Two mutations with disjoint predicted sets, both confirmed exactly:
M-1 the build drops two rows in three, so the index misses entries
predicted the four "answers its operator" arms and NOT the build arms
observed exactly those four, 16 passed + 4 failed
CREATE INDEX still succeeds, so every build arm stayed green
M-2 the build errors, so CREATE INDEX fails
predicted the four "builds an index" arms
observed those four plus the GiST overlap premise, 15 passed + 5 failed
AND M-2 SHOWS A WEAKNESS IN THE FOUR ANSWER ARMS. With no index in
existence they all stayed GREEN. The arm compares a count taken with
`enable_seqscan = off` against one taken with the custom scan off, and
enable_seqscan is a preference rather than a prohibition -- with no index
both sides fall back to the same scan and agree. An arm named "answers its
operator with the same rows the scan returns" can be satisfied without an
index scan happening. Reported on commandprompt#1236, not repaired here.
Rows produced by `pgc_ledger.py merge`, one merge per mutation, --target
for every arm that reddened. Control 20/20 before each, source restored and
md5-verified after each, clean re-run after the last.
Census 1519 -> 1510, counted. The reading list drops 72 -> 64.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MpajdQbkVJ9ey1XyYHcikP
77a5955 to
9db9232
Compare
|
Rebased onto Neither side's number was right for the composed tree, so neither was taken. Cross-checked against the other route: main's 1521 minus the nine rows this The nine rows split exactly as the budget note predicts, which is worth stating Verified on the composed tree, not on the pre-rebase branch: No suite code changed: the diff is 3 files, all evidence -- the ledger rows, the Two instrument faults on the way, both mine and both caught before they could 🤖 Generated with Claude Code |
jdatcmd
left a comment
There was a problem hiding this comment.
Approving 9db9232e. Verified by deriving from the artifact rather than reading the body.
What changed
ledger rows changed 9, every one never -> 2026-09-23, none the other way
majors unchanged on all 9
byte-identical moves 0
rows added or removed 0
census 1606 rows, 1512 never, 94 not-never, 1512 + 94 == 1606
budget states 1512, agrees, and 1521 - 9 = 1512 against main
files CHANGELOG.md, check_ledger.tsv, check_ledger_budget.txt
Attribution counted on the exact mutation strings in the ledger this PR ships, not from the description:
M-2 pgcolumnar_index_build_range_scan errors, so CREATE INDEX fails 5 arms
M-1 ... drops two rows in three, so the index misses entries 4 arms
which matches "four, plus those four and the GiST overlap premise" exactly.
The accounting lines are in the body and they close the complement: constant total 20, nothing unrunnable, nothing skipped, so every arm outside each target set ran and passed. That is the half the ledger cannot carry — an arm that was unrunnable under a mutation is not red, is not named, and is indistinguishable afterwards from one that passed.
The finding is worth more than the rows
With no index in existence at all, the four answers its operator arms stay green. enable_seqscan is a preference and not a prohibition, so with no index both sides of the comparison fall back to the same scan and agree. An arm named btree answers its operator with the same rows the scan returns can be satisfied without an index scan ever happening.
That is not vacuity — M-1 reddens all four on a wrong answer — it is an arm whose NAME claims the index path was exercised while nothing checks that. Same class as the stat -c %F fixture facts in part 570, reached from the opposite direction: those were found by reading names, this by deleting the index and watching the arms hold.
Not repairing it here is the right call. The repair is one premise — assert the index path's plan contains an index scan — and a repair smuggled into a change whose subject is records evidence, alters no test is how a later reader loses track of which claims were measured. Reported on #1236 instead.
The pattern behind both batches
index_am_support's only dated rows were two premises about docs/features.md, reddened by a documentation mutation, which cannot reach an arm about what an index does. Eight behaviour arms sat never beside them.
That is the same shape as native_join_runtime_filter's GUC boot value in #1238, and it is why #1236's third clause is the one that does the work: a never arm in a part nobody has attacked says nothing, and a never arm in a part attacked only from outside its own subject is a question. Two for two — and the author has since refuted it as a general rule on the remaining 64, which is a better outcome than a third confirmation.
Six mutations over validity_elision, selftest part 190 and native_join_vector_agg. No test changed and no code changed: the arms were attacked and the ledger records what happened. veC the elision predicate forced true 5 arms b190A pgc_build_needs_clean never asks for a clean 5 arms b190B the stamp writes an escaped literal (commandprompt#898) 2 arms b190C pgc_build_needs_clean always demands a clean 2 arms b190D unknown provenance reported as a major, PG? 2 arms jvaB the dim-side uniqueness refusal disabled 2 arms b190A and b190C are opposites and redden disjoint pairs. A guard that never cleans loses the five arms about when a clean is required; one that always cleans loses exactly two, and only those two separate a correct guard from one that is merely fail-closed. Fifteen of the eighteen rows are newly dated. The other three are validity_elision arms already dated under the inverse mutation -- the predicate forced false rather than true -- so they now carry both strings and the later date, rather than the newer observation overwriting the older. Re-derived on the merged tree. All six had run once before commandprompt#1240 and commandprompt#1241 landed and were re-run against ac80762, reproducing their earlier results exactly: same names, not merely the same counts, with a control showing the comparison can separate two unrelated sets. The two C mutations ran with a forced make clean, because PGXS here has no --enable-depend and a stale object after a header edit would leave veC reddening nothing. Census re-derived by counting: 1606 rows, 109 not never, 1497 + 109 == 1606. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01MpajdQbkVJ9ey1XyYHcikP
Works #1236, second batch. No test changed and no code changed.
The same shape as the first batch
index_am_support's only dated rows were two premises aboutdocs/features.md, reddened by a docs mutation -- which cannot reach one arm about what an index does. Eight behaviour arms satneverbeside them: unattacked rather than vacuous.Two mutations with disjoint predicted sets, both confirmed exactly
M-1 leaving every builds an index arm green is the discriminating half:
CREATE INDEXstill succeeds when the index is merely incomplete, so the build arms should not move, and they do not.M-2 also shows a weakness in the four answer arms
With no index in existence at all, the four answers its operator arms stayed green.
The arm compares a count taken with
enable_seqscan = offagainst one taken withpgcolumnar.enable_custom_scan = off.enable_seqscanis a preference rather than a prohibition, so with no index both sides fall back to the same scan and agree. An arm named answers its operator with the same rows the scan returns can be satisfied without an index scan ever happening.The suite already guards the neighbouring case -- its own comment says "Two paths that both return nothing agree" and there is a premise that the predicate matches rows. This is the other one: both paths returning the same rows by taking the same path.
Reported on #1236 rather than repaired here. This change records evidence and alters no test, and a repair (assert the index path actually used an index) is a different change that should be reviewed as one.
Provenance
Rows produced by
pgc_ledger.py merge, one merge per mutation,--targetfor every arm that reddened. Not by a script editing the file.Discipline
Constant total, nothing unrunnable, nothing skipped, so every arm outside each target set ran and passed. Each anchor asserted to match exactly once; source restored and md5-verified after each.
Accounting
🤖 Generated with Claude Code
https://claude.ai/code/session_01MpajdQbkVJ9ey1XyYHcikP